package com.liyunc.demo.bundle.file.manager.web.resource;

import com.liyunc.demo.bundle.file.manager.model.dto.input.AssetFileContentUpdateDto;
import com.liyunc.demo.bundle.file.manager.model.dto.output.AssetFileDto;
import com.liyunc.demo.bundle.file.manager.model.dto.input.AssetFileContentRequestDto;
import com.liyunc.demo.bundle.file.manager.model.dto.input.AssetFileRequestDto;
import com.liyunc.demo.bundle.file.manager.service.AssetFileService;
import com.liyunc.demo.comp.common.rest.response.GeneralResponse;
import com.liyunc.demo.comp.common.utils.HttpResponseUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.Objects;

@RestController
@RequestMapping(
    value = "/api/v1/files",
    produces = {MediaType.APPLICATION_JSON_VALUE}
)
@Log4j2
@Validated
public class AssetFileResource {

    @Autowired
    private AssetFileService assetFileService;

    @RequestMapping(
        method = RequestMethod.POST,
        path = "",
        consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}
    )
    public GeneralResponse<AssetFileDto> upload(
        @NotNull @Valid AssetFileRequestDto requestDto
    ) {
        return GeneralResponse.of(
            assetFileService.upload(requestDto).orElse(null)
        );
    }

    @RequestMapping(
        method = RequestMethod.POST,
        path = "/scripts",
        produces = {MediaType.APPLICATION_JSON_VALUE}
    )
    public GeneralResponse<AssetFileDto> upload(
        @NotNull @Valid @RequestBody AssetFileContentRequestDto requestDto
    ) {
        return GeneralResponse.of(
            assetFileService.upload(requestDto).orElse(null)
        );
    }

    @RequestMapping(
        method = RequestMethod.GET,
        path = "/{file_id}"
    )
    public ResponseEntity<InputStreamResource> download(
        @Valid @NotNull @Min(0) @PathVariable("file_id") Long fileId
    ) {
        Pair<File, AssetFileDto> result = assetFileService.download(fileId).orElse(null);
        if (Objects.isNull(result)
            || Objects.isNull(result.getLeft())
            || Objects.isNull(result.getRight())) {
            return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .build();
        }
        String filename = result.getRight().getFilename();
        String mimeType = result.getRight().getMimeType();
        File file = result.getLeft();
        return HttpResponseUtils.sendAttachment(filename, mimeType, file);
    }

    @RequestMapping(
        method = RequestMethod.PUT,
        path = "/scripts/{script_id}",
        produces = {MediaType.APPLICATION_JSON_VALUE}
    )
    public GeneralResponse<AssetFileDto> update(
        @NotNull @Min(0) @PathVariable("script_id") Long scriptId,
        @NotNull @Valid @RequestBody AssetFileContentUpdateDto updateDto
    ) {
        return GeneralResponse.of(
            assetFileService.update(scriptId, updateDto).orElse(null)
        );
    }

    @RequestMapping(
        method = RequestMethod.DELETE,
        path = "/{file_id}"
    )
    public GeneralResponse<AssetFileDto> delete(
        @Valid @NotNull @Min(0) @PathVariable("file_id") Long fileId
    ) {
        return GeneralResponse.of(
            assetFileService.delete(fileId).orElse(null)
        );
    }

}
